#include "dict.h"

void do_client(int ,sqlite3*);

void do_register(int,message*,sqlite3*);

void do_login(int,message*,sqlite3*);

void do_query(int,message*,sqlite3*);

int insert_sqlite(sqlite3 *data,char *name,char *word,char *meaning);

void do_history(int,message* ,sqlite3 *);

int main(int argc, const char *argv[])
{
    int listenfd,connectfd;
    struct sockaddr_in server_addr;
    pid_t pid;
    sqlite3 *data;

    if(argc < 3){
        printf("usage : %s <ip> <port> \n",argv[0]);
        exit(-1);
    }

    if(sqlite3_open("my.db",&data) != SQLITE_OK){
        printf("errer:%s\n",sqlite3_errmsg(data));
        exit(-1);
    }
    if((listenfd = socket(PF_INET,SOCK_STREAM,0)) < 0){
        perror("fail to socket");
        exit(-1);
    }

    bzero(&server_addr,sizeof(server_addr));
    server_addr.sin_family = PF_INET;
    server_addr.sin_addr.s_addr = inet_addr(argv[1]);
    server_addr.sin_port = htons(atoi(argv[2]));

    if(bind(listenfd,(struct sockaddr *) &server_addr,sizeof(server_addr)) < 0){
        perror("fail to bind");
        exit(-1);
    }
    if(listen(listenfd,5) < 0){
        perror("fail to listen");
        exit(-1);
    }
    signal(SIGCHLD,SIG_IGN);
    while(1){
        if((connectfd = accept(listenfd,NULL,NULL)) < 0){
            perror("fail to accept");
            exit(-1);
        }
        if((pid = fork()) < 0){
            perror("fail to fork");
            exit(-1);
        }
        if(pid == 0){
            do_client(connectfd,data);
        }
        close(connectfd);
    }
    return 0;
}

void do_client(int connectfd,sqlite3 *data){
    message msg;

    puts("do_client");

    while(recv(connectfd,&msg,sizeof(message),0) > 0){
        printf("msg.name:%s msg.data:%s\n",msg.name,msg.data);
        switch(msg.type){
        case R:
            puts("R");
            do_register(connectfd,&msg,data);
            break;
        case L:
            puts("L");
            do_login(connectfd,&msg,data);
            break;
        case Q:
            puts("Q");
            do_query(connectfd,&msg,data);
            break;
        case H:
            puts("H");
            do_history(connectfd,&msg,data);
            break;
        default:
            puts("wrong msg type:");
        }
    }
    puts("client quit");
    close(connectfd);
    exit(0);
}

void do_register(int connectfd,message *msg,sqlite3 *data){
    char sqlcmd[DATA_MAX] = {0};
    char *errmsg;

    sprintf(sqlcmd,"insert into usr(name,passwd) values('%s','%s')",msg->name,msg->data);

    if(sqlite3_exec(data,sqlcmd,NULL,NULL,&errmsg) != SQLITE_OK){
        sprintf(msg->data,"register :%s\n",errmsg);
    }else{
        strcpy(msg->data,"register is ok");
    }
    printf("msg->name:%s,msg->data:%s\n",msg->name,msg->data);
    send(connectfd,msg,sizeof(message),0);
    return ;
}

void do_login(int connectfd,message *msg,sqlite3* data){
    char sqlcmd[DATA_MAX] = {0};
    char *errmsg;
    char **result;
    int nrow = 0;
    int ncolumn = 0;

    sprintf(sqlcmd,"select * from usr where name = '%s' and passwd = '%s'",msg->name,msg->data);

    puts(sqlcmd);

    if(sqlite3_get_table(data,sqlcmd,&result,&nrow,&ncolumn,&errmsg) != SQLITE_OK){
        printf("do_login error!:%s \n",errmsg);
    }

    if(nrow == 1)
    {
        strcpy(msg->data,"Login is ok!");
        msg->type = OK;
    }else{
        strcpy(msg->data,"Usr name or the passwd is wrong!");
    }
    printf("%d:%s\n",__LINE__,msg->data);
    send(connectfd,msg,sizeof(message),0);
    return ;
}
void do_query(int connectfd,message* msg,sqlite3* data){
   char sqlcmd[DATA_MAX] = {0};
   char word  [WORD_MAX] = {0};
   char **result;
   char *errmsg; 
   int  nrow;
   int  ncolumn;

   printf("your name:%s ,your word :%s\n",msg->name,msg->data);

   strcpy(word,msg->data);

   sprintf(sqlcmd,"select * from dict where word = '%s'",msg->data);

   puts(sqlcmd);

   if(sqlite3_get_table(data,sqlcmd,&result,&nrow,&ncolumn,&errmsg) != SQLITE_OK){
       printf("sqlite3_get_table is error!");
   }

   if(!nrow){
      strcpy(msg->data,"your word is not found"); 
   }else{
      msg->type = OK;
      printf("data:%s\n",result[3]);
      strcpy(msg->data,result[3]);
      if(insert_sqlite(data,msg->name,word,msg->data)){
        puts("insert_sqlite error!");
      }
   }

   puts(msg->data);
   send(connectfd,msg,sizeof(message),0);
   return;
}

int insert_sqlite(sqlite3 *data,char *name,char *word,char *meaning){
    char        sqlcmd[DATA_MAX]  = {0};
    time_t      t;
    struct tm   *tp;
    char        *errmsg;
    
    time(&t);
    tp = localtime(&t);

    sprintf(sqlcmd,"insert into record values('%d-%d-%d %d:%d:%d','%s','%s','%s')",
        tp->tm_year + 1900,tp->tm_mon,tp->tm_mday,tp->tm_hour,tp->tm_min,tp->tm_sec,name,
        word,meaning);

    if(sqlite3_exec(data,sqlcmd,NULL,NULL,&errmsg) != SQLITE_OK){
        printf("insert record error:%s\n",errmsg);
        return -1;
    }
    return 0;
}

void do_history(int connectfd,message * msg,sqlite3 *data){
    char    sqlcmd[DATA_MAX] = {0};
    char    str[DATA_MAX]    = {0};
    int     nrow;
    int     ncolumn;
    char**  result;
    char*   errmsg;
    

    sprintf(sqlcmd,"select * from record where name = '%s'",msg->name);

    if(sqlite3_get_table(data,sqlcmd,&result,&nrow,&ncolumn,&errmsg) != SQLITE_OK){
        printf("sqlite3_get_table error:%s\n",errmsg);
    }

    int i = 0;

    if(nrow){
        for(i = ncolumn ;i < (nrow + 1) * ncolumn;i = i + ncolumn){

            sprintf(str,"%s %s %s %s",result[i],result[i + 1],result[i + 2],
                result[i + 3]);
            strcpy(msg->data,str);
            send(connectfd,msg,sizeof(message),0);
        }
        memset(msg,0,sizeof(message));
        send(connectfd,msg,sizeof(message),0);
    }else{
        strcpy(msg->data,"no record");
        send(connectfd,&msg,sizeof(message),0);
    }
    puts("exit do_history");

    return ;
}
